#include<cstdio>
#include<algorithm>

using namespace std;

const int N = 20100;
const int INF = 1e9;

struct Edge{
    int to,c,nxt;
}e[500100];

int q[5000100],head[N],dis[N],cur[N];
int S,T,n,m,L,R,tot = 1;

inline char nc() {
    static char buf[100000],*p1 = buf,*p2 = buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
}
inline int read() {
    int x = 0,f = 1;char ch = nc();
    for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f = -1;
    for (; ch>='0'&&ch<='9'; ch = nc()) x = x * 10 + ch - '0';
    return x * f;
}
inline void add_edge(int u,int v,int w) {
    e[++tot].to = v,e[tot].c = w,e[tot].nxt = head[u],head[u] = tot;
    e[++tot].to = u,e[tot].c = 0,e[tot].nxt = head[v],head[v] = tot;
}
inline bool bfs() {
    for (int i=1; i<=n; ++i) {
        cur[i] = head[i];dis[i] = -1;
    }
    L = 1;R = 0;
    q[++R] = S;
    dis[S] = 0;
    while (L <= R) {
        int u = q[L++];
        for (int i=head[u]; i; i=e[i].nxt) {
            int v = e[i].to,c = e[i].c;
            if (dis[v]==-1 && c>0) {
                q[++R] = v;
                dis[v] = dis[u] + 1;
                if (v==T) return true;
            }
        }
    }
    return false;
}
int dfs(int u,int flow) {
    if (u==T) return flow;
    int used = 0;
    for (int & i=cur[u]; i; i=e[i].nxt) {
        int v = e[i].to,c = e[i].c;
        if (dis[v]==dis[u]+1 && c>0) {
            int tmp = dfs(v,min(c,flow-used));
            if (tmp > 0) {
                e[i].c -= tmp;e[i^1].c += tmp;
                used += tmp;
                if (used==flow) break;
            }
        }
    }
    if (used != flow) dis[u] = -1;
    return used;
}
inline int dinic() {
    int ans = 0;
    while (bfs())
        ans += dfs(S,INF);
    return ans;
}

int main()
{
    while(scanf("%d%d%d%d",&n,&m,&S,&T)!=EOF)
    {
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
        }
        printf("%d\n",dinic());
    }
}
